package com.ft.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ft.domain.Message;
import com.ft.domain.User;
import com.ft.dao.UserDao;
import com.ft.domain.UserAddress;
import com.ft.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ft.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author com/ft
 * @since 2022-08-24
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements IUserService {
    @Autowired
    UserDao userdao;
    @Autowired
    RedisTemplate redisTemplate;

    /**
     *
     * @param username 传入的手机号，ID
     * @param password 传入的密码
     * @return 0.没有查询到信息，1.验证成功,-1没查询到，-2查询到；(0,1手机登录，-1，-2ID登录)
     */
    @Override
    public int loginCheckUser(String username, String password) {
        /**
         * 对用户名进行校验，看是ID登录还是手机号
         */
        //手机号的情况
        if(username.length() == 11){
            String s = userdao.selectByPhone(username, password);
            if(s == null || s.length() == 0){
                return 0;
            }else {
                return 1;
            }
        }else{ //ID的情况
            String s = userdao.selectByID(username, password);
            if(s == null || s.length() == 0){
                return -1;
            }else {
                return -2;
            }
        }
    }

    /**
     * 发送验证码功能
     *
     * @param phone 传入的接收验证码的手机号
     * @return 0：失败，1：验证码还在时效内，2：发送成功,3一小时只能发送5次验证码，4一天只能发送10次验证码
     */
    @Override
    public int sendMessage(String phone) {
        //获取发送验证码每天的总数
        String total = String.valueOf(redisTemplate.opsForValue().get(phone + "total"));
        //获取每小时发送验证码的次数
        String hour = String.valueOf(redisTemplate.opsForValue().get(phone + "hour"));
        //第一次发送的情况
        if ("null".equals(total) | total.length() == 0 && "null".equals(hour) | total.length() == 0) {
            //获取验证码
            String number = SmsUtils.getNumber();
            int i = SmsUtils.sendMessage(phone, number);
            //返回2发送成功，0,1出现异常
            if (i == 2) {
                //将发送的验证码存入redis
                redisTemplate.opsForValue().set(phone, number, 60, TimeUnit.SECONDS);
                //增加次数
                redisTemplate.opsForValue().set(phone + "total", 1, 1, TimeUnit.DAYS);
                redisTemplate.opsForValue().set(phone + "hour", 1, 1, TimeUnit.HOURS);
                return 2;
            } else {
                //验证码时发送出现问题
                return 0;
            }
        } else {//不是第一次的情况
            if (! "null".equals(total) && Integer.valueOf(total) >= 10) {
                return 4;
            }
            //每小时发送次数上线
             else if ( ! "null".equals(hour) && Integer.valueOf(hour) >= 5) {
                return 3;
            } else {
                //1.查询redis中有对应手机号的验证码没
                String str = String.valueOf(redisTemplate.opsForValue().get(phone));
                if ("null".equals(str) || str.length() == 0) {
                    //获取验证码
                    String number = SmsUtils.getNumber();
                    int i = SmsUtils.sendMessage(phone, number);
                    //返回2发送成功，0,1出现异常
                    if (i == 2) {
                        //将发送的验证码存入redis
                        redisTemplate.opsForValue().set(phone, number, 60, TimeUnit.SECONDS);
                        //不是第一次就增加次数
                        if("null".equals("null") || hour.length() == 0){
                            redisTemplate.opsForValue().set(phone + "total", Integer.valueOf(total) + 1, 0);
                            redisTemplate.opsForValue().set(phone + "hour", 1, 1, TimeUnit.HOURS);
                        }else {
                            redisTemplate.opsForValue().set(phone + "total", Integer.valueOf(total) + 1, 0);
                            redisTemplate.opsForValue().set(phone + "hour", Integer.valueOf(hour) + 1, 0);
                        }

                        return 2;
                    } else {
                        //验证码时发送出现问题
                        return 0;
                    }
                } else {
                    //验证码还在时效内
                    return 1;
                }
            }
        }
    }

    /**
     * 短信验证码登录校验
     *
     * @return 2成功，1验证码失效，0验证码错误,3创建用户错误
     */
    @Override
    public int PhoneLoginCheck(String phone, String code) {
        //先验证手机号和验证码是否正确
        String redisCode = String.valueOf(redisTemplate.opsForValue().get(phone));
        //验证码为空则失效，
        if (redisCode == null || redisCode.length() == 0) {
            return 1;
        } else if (redisCode.equals(code)) {//传入的验证码和redis中的一致，进行下一步操作
            //先查询数据库中有对应手机号没有
            String s = userdao.selectRedisByPhone(phone);
            if (s == null || s.length() == 0) {
                //没有手机号说明是第一次登录,第一次登录默认注册
                User user = new User();
                user.setPhone(phone);
                //默认密码手机号后六位
                String substring = phone.substring(5, phone.length());
                String s1 = MD5Utils.md5(substring);
                user.setPassword(s1);
                user.setName(UserName.getname());
                user.setImg("https://ft-glb.oss-cn-chengdu.aliyuncs.com/user-img/%E7%94%A8%E6%88%B7.jpg");
                int i = userdao.addUser(user);
                if (i == 1) {
                    return 2;
                } else {
                    return 3;
                }
            } else {
                return 2;
            }
        } else {
            //验证码不正确
            return 0;
        }
    }

    /**
     * 发送重置密码验证码
     * @param phone
     * @return 0：失败，1：验证码还在时效内，2：发送成功,3一天只能发送3次验证码
     */
    @Override
    public int wjmmSendMessage(String phone) {
        //获取发送验证码每天的总数
        String total = String.valueOf(redisTemplate.opsForValue().get("reset"+phone + "total"));
        //第一次发送的情况
        if ("null".equals(total) | total.length() == 0) {
            //获取验证码
            String number = SmsUtils.getNumber();
            int i = SmsUtils.sendMessage(phone, number);
            //返回2发送成功，0,1出现异常
            if (i == 2) {
                //将发送的验证码存入redis
                redisTemplate.opsForValue().set("reset"+phone , number, 60, TimeUnit.SECONDS);
                //增加次数
                redisTemplate.opsForValue().set("reset"+phone + "total", 1, 1, TimeUnit.DAYS);
                return 2;
            } else {
                //验证码时发送出现问题
                return 0;
            }
        } else {//不是第一次的情况
            if (! "null".equals(total) && Integer.valueOf(total) >= 3) {
                return 3; //重置次数上限
            } else {
                //1.查询redis中有对应手机号的验证码没
                String str = String.valueOf(redisTemplate.opsForValue().get("reset"+phone));
                if ("null".equals(str) || str.length() == 0) {
                    //获取验证码
                    String number = SmsUtils.getNumber();
                    int i = SmsUtils.sendMessage(phone, number);
                    //返回2发送成功，0,1出现异常
                    if (i == 2) {
                        //将发送的验证码存入redis
                        redisTemplate.opsForValue().set("reset"+phone , number, 60, TimeUnit.SECONDS);
                        //不是第一次就增加次数
                        redisTemplate.opsForValue().set("reset"+phone +"total", Integer.valueOf(total) + 1, 1, TimeUnit.DAYS);
                        return 2;
                    } else {
                        //验证码时发送出现问题
                        return 0;
                    }
                } else {
                    //验证码还在时效内
                    return 1;
                }
            }
        }
    }

    /**
     * 重置密码
     * @param phone
     * @param code
     * @return
     */
    @Override
    public int resetPassword(String phone, String code,String password) {
        String str = String.valueOf(redisTemplate.opsForValue().get("reset"+phone));
        System.out.println("redis中的："+str);
        if(str.equals(code)){
            int i = userdao.resetPassword(phone,password);
            if(i == 1){
                return 1;
            }else {
                return 0;
            }
        }
        return 0;
    }

    /**
     * 添加用户，如果用户名已经存在返回false
     *
     * @param user 传入的用户对象
     * @return 0：成功，1：注册失败，2：用户名以存在
     */
    @Override
    public int addUser(User user) {
        String s = userdao.selectByName(user.getName());
        if (s == null) {
            String str = user.getPassword();
            String psd = MD5Utils.md5(str);
            user.setPassword(psd);
            int i = userdao.addUser(user);
            if (i > 0) {
                return 0;
            }
            return 1;
        } else {
            return 2;
        }
    }

    /**
     * 修改用户
     *
     * @param user 传入修改的用户对象
     * @return 返回受影响的行数
     */
    @Override
    public int updateUser(User user) {
        String str = user.getPassword();
        String s = MD5Utils.md5(str);
        user.setPassword(s);
        int i = userdao.updateUser(user);
        return i;
    }

    @Override
    public List<User> selectAll() {
        List<User> userList = userdao.selectAll();
        return userList;
    }

    /**
     * 更加id查询用户所有信息
     * @param id
     * @return
     */
    @Override
    public User selectUserInfoById(int id) {
        User user = userdao.selectUserAllById(id);
        return user;
    }

    /**
     * 根据传入的用户id对用户做逻辑删除
     *
     * @param id 要删除用户的id
     * @return 返回受影响的结果
     */
    @Override
    public int deleteUser(int id) {
        int i = userdao.deleteUser(id);
        return i;
    }

    /**
     * 查询已经逻辑删除的用户
     *
     * @return 返回查询的list集合
     */
    @Override
    public List<User> selectByState() {
        List<User> users = userdao.selectByState();
        return users;
    }

    /**
     * 根据手机号查询用户
     *
     * @param phone 查询的手机号
     * @return 返回用户对象
     */
    @Override
    public User selectUserByPhone(String phone) {
        //手机号校验
        if (phone == null || phone.length() == 0) {
            User user = new User();
            return user;
        }
        User user = userdao.selectUserByPhone(phone);
        return user;
    }

    /**
     * 根据ID查询用户
     * @param ID 查询的手机号
     * @return 返回用户对象
     */
    @Override
    public User selectUserByID(String ID) {
        //手机号校验
        User user = userdao.checkSelectById(ID);
        return user;
    }

    @Override
    public int getUserSex(int id) {
        int userSex = userdao.getUserSex (id);
        return userSex;
    }

    /**
     * 根据传入的页码查询页面的数据
     *
     * @param page 要查询的第几页的页码
     * @return 返回查询的List结果集
     */
    @Override
    public List<User> selectDataByPage(int page) {
        //使用mybatis-puls分页功能
        IPage page1 = new Page(page, 4);
        userdao.selectPage(page1, null);
        //返回当前页面的数据
        System.out.println(page1.getRecords());
        return page1.getRecords();
    }

    /**
     * 获取用户好友列表
     * @return 用户列表集合
     */
    @Override
    public List<User> getUserList(String userid) {
        //创建好要返回的list
        List<User> friendsList = new ArrayList<>();
        //从redis中获取好友列表id
        Set<Integer> mem = redisTemplate.opsForSet().members(userid+"FriendList");
        if (mem.size() > 0) {
            List members = new ArrayList();
            for(Integer id : mem){
                members.add(id);

            }
            //查询所有好友列表的img
            List<User> userList = userdao.getUserImgList(members);
            for(int i = 0;i < members.size(); i++){
                User user = new User();
                user.setId((Integer) members.get(i));
                user.setImg(userList.get(i).getImg());
                user.setName(userList.get(i).getName());
                user.setLastmessage("");
                user.setTotalMessage(0);
                friendsList.add(user);
            }
            return friendsList;
        }else {
            return friendsList;
        }
    }
    /**
     * 根据传入的地址增加用户地址信息
     * @param str 地址信息
     * @return 0增加失败，1增加成功,2地址已达上限
     */
    @Override
    public int addUserAddress(UserAddress str,int id) throws JsonProcessingException {
        //先查询用户的地址信息
        List<UserAddress> s = selectAddress(id);
        if(s.size() == 0){
            s.add(str);
            int i = userdao.updateAddress(JSON.toJSONString(s), id);
            return i;
        }else{//不是第一次的情况
                if(s.size() < 3){
                    s.add(str);
                    int i = userdao.updateAddress(JSON.toJSONString(s), id);
                    return i;
                }else {
                    return 2;
                }
            }
    }

    /**
     * 查询用户地址信息
     * @return
     */
    @Override
    public List<UserAddress> selectAddress(int id){
        String s = userdao.selectAddress(id);
        //对空处理
        if(s == null || s.length() == 0){
            List<UserAddress> list = new ArrayList<UserAddress>();
            return list;
        }else{
            //将字符串转成List
            ArrayList<UserAddress> userAddresses = ArrayUtils.atoString(s);
            return userAddresses;
        }
    }

    /**
     * 根据指定下标删除用户地址
     * @param index 待删除的地址下标
     * @return
     */
    @Override
    public int deleteUserAddress(int id ,int index) {
        List<UserAddress> userAddresses = selectAddress(id);
        userAddresses.remove(index);
        int i = userdao.updateAddress(JSON.toJSONString(userAddresses), id);
        return i;
    }
    /**
     * 修改用户地址信息
     * @param id 修改地址的用户id
     * @param userAddress 修改用户的地址
     * @return 受影响的行数
     */
    @Override
    public int updateUserAddress(int id, Object userAddress) {
        int i = userdao.updateAddress(JSON.toJSONString(userAddress), id);
        return i;
    }

    /**
     * 获取离线用户信息
     * @param userid
     * @return
     */
    @Override
    public List getOfflineUsermessage(int userid) {
        List result = new ArrayList<>();
        String key = userid+":offline:";
        String key2 = userid+":offlineList";
        Set messagelist = redisTemplate.opsForZSet ().reverseRangeByScore(key2, 1, 999);
        List ids = new ArrayList<>(messagelist);
        //获取用户离线数据返回
        for(int i = 0;i < ids.size(); i++){
            Map entries = redisTemplate.opsForHash ().entries (key+ ids.get (i));
            //对订单号处理成字符串，防止前端精度丢失
            Object id = entries.get ("id");
            entries.put ("id",""+id);
            result.add (entries);
        }
        return result;
    }

    /**
     * 增加用户离线信息
     * @param message
     * @return
     */
    @Override
    public int addOfflineUsermessage(Message message) throws IllegalAccessException {
        //创建消息id
        SnowFlakeGenerateIdWorker snowFlakeGenerateIdWorker =
                new SnowFlakeGenerateIdWorker(0L,0L);
        String id = snowFlakeGenerateIdWorker.generateNextId();
        //封装key
        String key = message.getReceiveUser()+":offline:"+id;
        message.setId(id);
        //将key存入redishash中
        Map<String, Object> stringObjectMap = ObjectUtils.objectToMap (message);
        System.out.println(stringObjectMap);
        redisTemplate.opsForHash ().putAll(key,stringObjectMap);
        //将id添加到zset集合中
        String key2 =  message.getReceiveUser()+":offlineList";
        Long zsetSize = redisTemplate.opsForZSet().zCard(key2);
        redisTemplate.opsForZSet().add(key2, id,1);
        Long zsetSizeNew = redisTemplate.opsForZSet().zCard(key2);
        if(zsetSizeNew > zsetSize){
            return 1;
        }
        return 0;
    }

    /**
     * 删除用户离线信息
     * @param userid
     * @return
     */
    @Override
    public int deleteOfflineUsermessage(int userid) {
        //获取所有用户离线消息集合
        String key = userid+":offline:";
        String key2 = userid+":offlineList";
        Set messagelist = redisTemplate.opsForZSet ().reverseRangeByScore(key2, 1, 999);
        for(Object o : messagelist) {
            System.out.println(o);
            //删除评论hash表
            redisTemplate.delete (key+o);
            //删除评论zet中对应id
            redisTemplate.boundZSetOps(key2).remove(""+o);
        }
        return 1;
    }

    /**
     * 添加好友列表
     * @param userid
     * @return
     */
    @Override
    public int addUserFrientList(String userid,int touserid){
        Long oldnum = redisTemplate.opsForSet().size(userid + "FriendList");
        redisTemplate.opsForSet().add(userid + "FriendList",touserid);
        Long newnum = redisTemplate.opsForSet().size(userid + "FriendList");
        if(newnum > oldnum){
            redisTemplate.opsForSet().add(touserid + "FriendList",Integer.valueOf(userid));
            return 1;
        }
        return 0;
    }

    @Override
    public int updateUserInfo(User user) {
        int i = userdao.updateUserInfo(user);
        if(i == 1){
            return  1;
        }
        return 0;
    }
    @Override
    public double getUserMeney(int userid){
        double userMoney = userdao.getUserMoney(userid);
        return userMoney;
    }
}
